package conMgr.ui.util;

import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;

import conMgr.model.Conference;
import conMgr.ui.bases.JDialogEx;

/**
 * Provides a dialog that lets the conference select from the list of all conference.
 * @author Soon Bang.
 */
public class SelectConferenceView extends JDialogEx
{

	/**
	 * The serialization ID for this class.
	 */
	private static final long serialVersionUID = -591817004457560171L;
	/**
	 * The date pattern.
	 */
	private static final String datePattern = "MM-dd-yyyy";
	/**
	 * The button bar for this dialog.
	 */
	private final ButtonBar buttonBar;
	
	/**
	 * The selected conference.
	 */
	private Conference selectedConference;
	
	/**
	 * The list of conferences.
	 */
	private final List<Conference> conferences;
	
	/**
	 * The table of all conference.
	 */
	private final JTable conferenceTable;
	
	/**
	 * The date formatter.
	 */
	private final SimpleDateFormat formatter;
	
	/**
	 * Today.
	 */
	private final Date today = new Date();
	
	/**
	 * Initializes a new Select Conference View.
	 */
	private SelectConferenceView()
	{
		
		setTitle("Select a Conference.");
		formatter = new SimpleDateFormat(datePattern);
		conferences = getAllConferences();
		conferenceTable = addTable();
		
		final GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = Ui.DEFAULT_INSETS;
		constraints.gridx = 0;
		constraints.gridy = 1;
		constraints.anchor = GridBagConstraints.NORTHEAST;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		buttonBar = new ButtonBar();
		buttonBar.addButton("Select", new OkAction());
		buttonBar.addButton("Cancel", new CancelAction());
		add(buttonBar, constraints);
		
		finishSetup();
		setLocationRelativeTo(null);
	}
	
	/**
	 * Adds the conference table to the dialog.
	 * @return The table.
	 */
	private JTable addTable()
	{
		final GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = Ui.DEFAULT_INSETS;
		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.anchor = GridBagConstraints.CENTER;
		
		final JTable table = new JTable(new ConferenceTableModel(conferences));
		Ui.packTable(table);
		
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		final JScrollPane pane = new JScrollPane(table);
		add(pane, constraints);
		
		return table;
	}
	
	/**
	 * Gets a list of conferences. 
	 * @return A list of all conference.
	 */
	private List<Conference> getAllConferences()
	{
		final List<Conference> conferences = new ArrayList<Conference>();
		
	    for (Conference conf : Conference.getAllConferences())
	    	if (today.before(conf.getSubmissionDL()))
	    		conferences.add(conf);
		
		return conferences;
	}
	
	/**
	 * Gets a conference by displaying this dialog.
	 * @return The selected conference or null if none was selected.
	 */
	public static Conference getConference()
	{
		final SelectConferenceView view = new SelectConferenceView();
		
		view.setVisible(true);
		
		if (view.selectedConference != null)
			return view.selectedConference;
		return null;
	}
	
	/**
	 * Provides an action for the OK button. 
	 */
	class OkAction extends AbstractAction
	{

		/**
		 * The serialization ID for this class.
		 */
		private static final long serialVersionUID = 3353606241431113309L;

		/**
		 * Handles the action. Creates or updates the given paper and closes the
		 * window.
		 */
		@Override
		public void actionPerformed(final ActionEvent arg0)
		{
			if (conferenceTable.getSelectedRows().length == 0)
			{
				JOptionPane.showMessageDialog
				(
					null,
					"Please select a conference from the list.",
					"No Conference Selected",
					JOptionPane.ERROR_MESSAGE
				);
				return;
			}
			for (int i : conferenceTable.getSelectedRows())
					selectedConference = conferences.get(i);

			SelectConferenceView.this.close();
		}
	}
	
	/**
	 * Provides an action for the Cancel button.
	 */
	class CancelAction extends AbstractAction
	{
		/**
		 * The serialization ID for this class.
		 */
		private static final long serialVersionUID = -1569259579002207732L;

		/**
		 * Handles the action. Closes the window.
		 */
		@Override
		public void actionPerformed(final ActionEvent arg0)
		{
			SelectConferenceView.this.close();
		}
	}
	
	/**
	 * Provides a table model for conference classes.
	 * @author Soon Bang.
	 */
	class ConferenceTableModel extends AbstractTableModel
	{
		/**
		 * The serialization ID for this class.
		 */
		private static final long serialVersionUID = -20493403989734719L;
		
		/**
		 * The list of conferences to display.
		 */
		private final List<Conference> conferences;
		
		/**
		 * Initializes a new conference table model.
		 * @param users The list of conferences to display.
		 */
		private ConferenceTableModel(final List<Conference> conferences)
		{
			this.conferences = conferences;
		}
		
		/**
		 * Gets the number of columns to display.
		 */
		@Override
		public int getColumnCount()
		{
			return 6;
		}

		/**
		 * Gets the name of the column at the specified index.
		 * @param column The column to get the name of.
		 * @return The name of the column at the specified index. 
		 */
		@Override
		public String getColumnName(int column)
		{
			switch (column)
			{
				case 0: return "Name";
				case 1: return "Submission DL";
				case 2: return "Review DL";
				case 3: return "Revision DL";
				case 4: return "Recommendation DL";
				case 5: return "ProgramChair";
				default: return "";
			}
		};
		
		/**
		 * Gets the number of rows to display.
		 */
		@Override
		public int getRowCount()
		{
			return conferences.size();
		}

		/**
		 * Gets the value at the given row and column.
		 * @param row The row to get the value for.
		 * @param column The column to get the value for.
		 */
		@Override
		public Object getValueAt(final int row, final int column)
		{
			final Conference conf = conferences.get(row);
			
			switch (column)
			{
				case 0: return conf.getName();
				case 1: return formatter.format(conf.getSubmissionDL());
				case 2: return formatter.format(conf.getReviewDL());
				case 3: return formatter.format(conf.getRevisionDL());
				case 4: return formatter.format(conf.getRecommendationDL());
				case 5: return conf.getProgramChair().getName();
				default: return "";
			}
		}
	}
}
